﻿using SuperX.Common.Collection;
using SuperX.Common.Log;
using SuperX.SuperSocket.Socket.Message;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SuperX.SuperSocket.Socket.Server
{
    public class WorkThreadManager
    {
        private SocketServer _socketServer;
        private ConcurrentDictionary<string, Thread> _workThreads;
        private ConcurrentDictionary<string, bool> _workThreadStatuss;
        private ConcurrentDictionary<string, ConcurrentList<MessageArgs>> _messages;

        public WorkThreadManager(SocketServer socketServer)
        {
            _socketServer = socketServer;
            _workThreads = new ConcurrentDictionary<string, Thread>();
            _workThreadStatuss = new ConcurrentDictionary<string, bool>();
            _messages = new ConcurrentDictionary<string, ConcurrentList<MessageArgs>>();
        }

        public void AddMessage(string sessionId, MessageArgs message)
        {
            if (!_messages.ContainsKey(sessionId))
            {
                _messages.TryAdd(sessionId, new ConcurrentList<MessageArgs>());
            }
            _messages[sessionId].Add(message);
        }

        public void CreateThread(string sessionId)
        {
            if (!_workThreadStatuss.ContainsKey(sessionId))
            {
                _workThreadStatuss.TryAdd(sessionId, true);
            }
            else
            {
                _workThreadStatuss[sessionId] = true;
            }
            if (!_workThreads.ContainsKey(sessionId))
            {
                var thread = new Thread(MessageInvoke);
                _workThreads.TryAdd(sessionId, thread);
                thread.Start(sessionId);
            }
            else
            {
                Logger.Error($"{sessionId} 工作线程已存在");
            }
        }

        private void MessageInvoke(object obj)
        {
            var id = obj.ToString();
            while (_workThreadStatuss[id])
            {
                if (_messages.ContainsKey(id) && _messages[id].Count > 0)
                {
                    var message = _messages[id].GetAndRemoveAt(0);
                    _socketServer?.FireMessageInvoke(message);
                }
                Thread.Sleep(10);
            }
        }

        public Task CloseThread(string sessionId)
        {
            var task = Task.Factory.StartNew(() =>
            {
                try
                {
                    if (_workThreadStatuss.ContainsKey(sessionId))
                    {
                        _workThreadStatuss[sessionId] = false;
                    }
                    if (_workThreads.ContainsKey(sessionId))
                    {
                        var thread = _workThreads[sessionId];
                        var time = DateTime.Now;
                        while (true)
                        {
                            if ((DateTime.Now - time).TotalSeconds > 20)
                            {
                                try
                                {
                                    thread.Abort();
                                }
                                catch { }
                                break;
                            }
                            Thread.Sleep(1000);
                        }
                    }
                    _workThreads.TryRemove(sessionId, out _);
                    _workThreadStatuss.TryRemove(sessionId, out _);
                    _messages.TryRemove(sessionId, out _);
                }
                catch
                {
                }
            });
            return task;
        }

        public void Close()
        {
            var keys = _workThreads.Keys.ToList();
            foreach (var id in keys)
            {
                CloseThread(id);
            }
        }
    }
}